14. Code Checkpoint: Testing Global App Navigation

L5 P4 A12 Testing Global App Navigation V2

In this step, you'll test app level navigation, including:

  • The navigation drawer
  • The app toolbar
  • The Up button
  • The Back button

Step 1: Create AppNavigationTest

  1. Create a file and class called AppNavigationTest.kt in androidTest:

Set up your test similarly to how you set up TasksActivityTest.

  1. Add the appropriate annotations for a class that uses AndroidX Test libraries and is an end-to-end test.
  2. Set up your taskRepository.
  3. Register and unregister the correct idling resources.

When done, AppNavigationTest should look like this:

AppNavigationTest.kt

@RunWith(AndroidJUnit4::class)
@LargeTest
class AppNavigationTest {

    private lateinit var tasksRepository: TasksRepository

    // An Idling Resource that waits for Data Binding to have no pending bindings.
    private val dataBindingIdlingResource = DataBindingIdlingResource()

    @Before
    fun init() {
        tasksRepository = ServiceLocator.provideTasksRepository(getApplicationContext())
    }

    @After
    fun reset() {
        ServiceLocator.resetRepository()
    }

    /**
     * Idling resources tell Espresso that the app is idle or busy. This is needed when operations
     * are not scheduled in the main Looper (for example when executed on a different thread).
     */
    @Before
    fun registerIdlingResource() {
        IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
        IdlingRegistry.getInstance().register(dataBindingIdlingResource)
    }

    /**
     * Unregister your idling resource so it can be garbage collected and does not leak any memory.
     */
    @After
    fun unregisterIdlingResource() {
        IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
        IdlingRegistry.getInstance().unregister(dataBindingIdlingResource)
    }

}

Step 2: Set up your Navigation tests

The starter code below outlines three tests and describes what they should do. Each test is setup so that it:

  • Configures the repository for the test.
  • Creates an ActivityScenario.
  • Properly sets up your DataBindingIdingResource.

Add the code now.

  1. Copy this code into the AppNavigationTest class:

AppNavigationTest.kt

@Test
fun tasksScreen_clickOnDrawerIcon_OpensNavigation() {
    // Start the Tasks screen.
    val activityScenario = ActivityScenario.launch(TasksActivity::class.java)
    dataBindingIdlingResource.monitorActivity(activityScenario)

    // 1. Check that left drawer is closed at startup.

    // 2. Open drawer by clicking drawer icon.

    // 3. Check if drawer is open.

    // When using ActivityScenario.launch(), always call close()
    activityScenario.close()
}

@Test
fun taskDetailScreen_doubleUpButton() = runBlocking {
    val task = Task("Up button", "Description")
    tasksRepository.saveTask(task)

    // Start the Tasks screen.
    val activityScenario = ActivityScenario.launch(TasksActivity::class.java)
    dataBindingIdlingResource.monitorActivity(activityScenario)

    // 1. Click on the task on the list.

    // 2. Click on the edit task button.

    // 3. Confirm that if we click Up button once, we end up back at the task details page.

    // 4. Confirm that if we click Up button a second time, we end up back at the home screen.

    // When using ActivityScenario.launch(), always call close().
    activityScenario.close().
}


@Test
fun taskDetailScreen_doubleBackButton() = runBlocking {
    val task = Task("Back button", "Description")
    tasksRepository.saveTask(task)

    // Start Tasks screen.
    val activityScenario = ActivityScenario.launch(TasksActivity::class.java)
    dataBindingIdlingResource.monitorActivity(activityScenario)

    // 1. Click on the task on the list.

    // 2. Click on the Edit task button.

    // 3. Confirm that if we click Back once, we end up back at the task details page.

    // 4. Confirm that if we click Back a second time, we end up back at the home screen.

    // When using ActivityScenario.launch(), always call close()
    activityScenario.close().
}

Step 3: Write your Navigation Tests

  1. Copy the getToolbarNavigationContentDescription extension function and add it to the end of AppNavigationTest.kt (outside of the class):

AppNavigationTest.kt

fun <T : Activity> ActivityScenario<T>.getToolbarNavigationContentDescription()
        : String {
    var description = ""
    onActivity {
        description =
            it.findViewById<Toolbar>(R.id.toolbar).navigationContentDescription as String
    }
    return description
}

The snippets of code below should help you complete the tests.

Here's an example of using the getToolbarNavigationContentDescription extension function to click on the navigation button:

Clicking the toolbar navigation button

onView(
    withContentDescription(
        activityScenario
            .getToolbarNavigationContentDescription()
    )
).perform(click())

This code checks whether the navigation drawer itself is either open or closed:

Checking that the navigation drawer is open

onView(withId(R.id.drawer_layout))
    .check(matches(isOpen(Gravity.START))) // Left drawer is open. 
onView(withId(R.id.drawer_layout))
    .check(matches(isClosed(Gravity.START))) // Left Drawer is closed.    

And here's an example of clicking the system back button:

Clicking the system Back button

pressBack()

// You'll need to import androidx.test.espresso.Espresso.pressBack. 
  1. Using the examples above and your knowledge of Espresso, finish tasksScreen_clickOnAndroidHomeIcon_OpensNavigation, taskDetailScreen_doubleUpButton(), and taskDetailScreen_doubleBackButton.
  2. Run your tests, and confirm everything works!

The completed test is in the end_codelab_3 branch of the repository here, so that you can compare.

Optional Step: Download the Final Code (Code Checkpoint)

This was the final code step! At this point, if you'd like, you can download the final code here, download a zip of the final code here, OR you can clone the Github repository for the code:

$ git clone https://github.com/udacity/android-testing.git
$ cd android-architecture
$ git checkout end_codelab_3